<template>
  <el-form ref="formRef" :model="form" v-bind="filterProps(props, 'form')">
    <p v-if="props.name" style="margin-bottom: 30px">{{ props.name }}</p>
    <el-form-item
      v-for="field in fields"
      v-bind="filterProps(field, 'formItem')"
      :key="field.key"
      :style="getItemStyle(field)"
    >
      <component :is="field.component" v-model="form[field.field]" v-bind="field.props">
        <template v-if="field.component === 'el-select'">
          <el-option v-for="o in field.options" :value="o.value" :label="o.label" />
        </template>
        <template v-if="field.component === 'el-checkbox-group'">
          <el-checkbox v-for="o in field.options" :value="o.value">{{ o.label }}</el-checkbox>
        </template>
        <template v-if="field.component === 'el-radio-group'">
          <el-radio v-for="o in field.options" :value="o.value">{{ o.label }}</el-radio>
        </template>
      </component>
    </el-form-item>
    <el-form-item>
      <el-button v-for="btn in props.actions" v-bind="btn" @click="$emit('handleClick', btn.event)">
        {{ btn.label }}
      </el-button>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import { watch, reactive, ref } from 'vue';
import { FormInstance } from 'element-plus';
const formRef = ref<FormInstance>();
const props = defineProps<{
  name?: string;
  fields: any[];
  actions?: any[];
  modelValue?: any;
  disabled?: boolean;
  labelWidth?: string | number;
  labelPosition?: 'left' | 'right' | 'top';
  size?: 'medium' | 'small' | 'large';
  inline?: boolean;
  labelSuffix?: string;
  hideRequiredAsterisk?: boolean;
  showMessage?: boolean;
  inlineMessage?: boolean;
  statusIcon?: boolean;
  validateOnRuleChange?: boolean;
  scrollToError?: boolean;
  rules?: any;
  onSubmit?: (form: any) => void;
  onValidate?: (valid: boolean, fields: any) => void;
  onValidateField?: (valid: boolean, field: any) => void;
}>();

const defaultValue = props.fields.reduce((result, field) => {
  if (props.modelValue && props.modelValue[field.field]) {
    result[field.field] = props.modelValue[field.field];
  } else if (field.defaultValue) {
    result[field.field] = field.defaultValue;
  } else if (field.component === 'el-checkbox-group') {
    result[field.field] = [];
  } else if (field.component === 'el-switch') {
    result[field.field] = false;
  } else {
    result[field.field] = '';
  }
  return result;
}, {});

const emit = defineEmits(['update:modelValue', 'handleClick']);

const form = ref(JSON.parse(JSON.stringify(defaultValue)));

watch(
  () => props.modelValue,
  newValue => {
    form.value = newValue;
  }
);

watch(
  () => form.value,
  newValue => {
    emit('update:modelValue', newValue);
  },
  { deep: true }
);

const filterProps = (props: any, type) => {
  const allprops = {
    form: ['inline', 'rules', 'labelPosition', 'labelWidth', 'labelSuffix'],
    formItem: ['label', 'prop', 'rules']
  };
  return Object.keys(props).reduce((result, key) => {
    if (allprops[type].includes(key)) {
      result[key] = props[key];
    }
    return result;
  }, {});
};
const getItemStyle = field => {
  if (field.width) {
    return { width: field.width + 'px' };
  }
};
const resetForm = () => {
  form.value = JSON.parse(JSON.stringify(defaultValue));
};
const submitForm = () => {
  console.log(form, defaultValue);
};
defineExpose({ resetForm });
</script>
